﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace BitcoinLibrary
{
    /**
     * <p>In Bitcoin the following format is often used to represent some type of key:</p>
     *
     * <pre>[one version byte] [data bytes] [4 checksum bytes]</pre>
     *
     * <p>and the result is then Base58 encoded. This format is used for addresses, and private keys exported using the
     * dumpprivkey command.</p>
     */
    public class VersionedChecksummedBytes
    {
        protected int version;
        protected byte[] bytes;

        protected VersionedChecksummedBytes(String encoded)
        {
            byte[] tmp = Base58.decodeChecked(encoded);
            version = tmp[0] & 0xFF;
            bytes = new byte[tmp.Length - 1];
            Array.Copy(tmp, 1, bytes, 0, tmp.Length - 1);
        }

        protected VersionedChecksummedBytes(int version, byte[] bytes)
        {
            Debug.Assert(version < 256 && version >= 0);
            this.version = version;
            this.bytes = bytes;
        }

        public override string ToString()
        {
            // A stringified address is:
            //   1 byte version + 20 bytes hash + 4 bytes check code (itself a truncated hash)
            byte[] addressBytes = new byte[1 + 20 + 4];
            addressBytes[0] = (byte)version;
            Array.Copy(bytes, 0, addressBytes, 1, 20);
            byte[] check = Utils.doubleDigest(addressBytes, 0, 21);
            Array.Copy(check, 0, addressBytes, 21, 4);
            return Base58.encode(addressBytes);
        }

        public override int GetHashCode()
        {
            return bytes.GetHashCode();
        }

        public override bool Equals(object o)
        {
            if (!(o is VersionedChecksummedBytes)) return false;
            VersionedChecksummedBytes vcb = (VersionedChecksummedBytes)o;
            return Array.Equals(vcb.bytes, bytes);
        }

        /**
         * Returns the "version" or "header" byte: the first byte of the data. This is used to disambiguate what the
         * contents apply to, for example, which network the key or address is valid on.
         * @return A positive number between 0 and 255.
         */
        public int getVersion()
        {
            return version;
        }
    }   
}
